package controllers;

import java.text.*;
import java.math.*;
import java.util.*;

import javax.persistence.*;

import play.*;
import play.mvc.*;
import models.*;
import play.data.validation.Required;

@Check("customer")
@With(Secure.class)
public class CustomerArea extends Controller {
	public static void index(){
		portfolio();
	}
	
	//Jin
	public static void portfolio(){	
		//Get username of current user
		String username = Security.connected();
		
		Customer customer = Customer.find("byUsername", username).first();
		List<Position> positionList = Position.find("byCustomer", customer).fetch();
		BigDecimal price=new BigDecimal(0);
		List<Fund> fundList = Fund.findAll();
		Map<Fund,BigDecimal> fundHoldMap = new HashMap<Fund,BigDecimal>();
		Map<Fund,BigDecimal> fundAllMap = new HashMap<Fund,BigDecimal>();
		Map<Fund,BigDecimal> availableSellSharesMap = new HashMap<Fund,BigDecimal>();
		for(int i=0;i<positionList.size();i++){
			FundPriceHistory priceHistory = FundPriceHistory.find("fund = ? order by price_date desc",
			        positionList.get(i).fund).first();
			if(priceHistory!=null){
				price=priceHistory.price;
			}
			else{
				price=new BigDecimal(0);
			}
			fundHoldMap.put(positionList.get(i).fund, price);
			availableSellSharesMap.put(positionList.get(i).fund,positionList.get(i).shares);
		}
		for(int i=0;i<fundList.size();i++){
			FundPriceHistory priceHistory = FundPriceHistory.find("fund = ? order by price_date desc",
			        fundList.get(i)).first();
			if(priceHistory!=null){
				price=priceHistory.price;
			}
			else{
				price=new BigDecimal(0);
			}
			fundAllMap.put(fundList.get(i), price);
		}
		List<Transaction> transactionList =Transaction.find("customer = ? and execute_date=null", customer).fetch();
		List<Transaction> buyList = new LinkedList();
		List<Transaction> sellList = new LinkedList();
		List<Transaction> checkList = new LinkedList();
		BigDecimal availableBalance=customer.cash;
		//available cash calculate and pending list
		for(int i=0;i<transactionList.size();i++){
			if(transactionList.get(i).transaction_type.equals("buy")){
				availableBalance = availableBalance.subtract(transactionList.get(i).amount);
				buyList.add(transactionList.get(i));
			}
			else if(transactionList.get(i).transaction_type.equals("sell")){
				sellList.add(transactionList.get(i));
				BigDecimal newShares = availableSellSharesMap.get(transactionList.get(i).position.fund).subtract(transactionList.get(i).shares);
				availableSellSharesMap.remove(transactionList.get(i).position.fund);
				 availableSellSharesMap.put(transactionList.get(i).position.fund,newShares);
				
			}
			else if(transactionList.get(i).transaction_type.equals("check")){
				availableBalance = availableBalance.subtract(transactionList.get(i).amount);
				checkList.add(transactionList.get(i));
			}
			else if(transactionList.get(i).transaction_type.equals("deposit")){
			
			}
		}
		
		renderArgs.put("username", username);
		renderTemplate("CustomerArea/portfolio.html",customer, positionList, price, fundList,fundHoldMap,fundAllMap,transactionList,availableBalance,checkList,buyList,sellList,availableSellSharesMap);

	}
	
	
	//Jin
	public static void check(String username,BigDecimal checkAmount){
		BigDecimal amount= checkAmount;
		Customer customer = Customer.find("byUsername", username).first();
		Fund fund = null;
		Position position = null;
		BigDecimal shares = null;
		Transaction newTransaction = new Transaction(customer, position, shares, "check", amount);
		newTransaction.save();
		portfolio();
	}
	
	//Jin
	public static void buy(String username, String fundSymbol, BigDecimal amountBuy, BigDecimal approxQuantity_Data){
		BigDecimal amount= amountBuy;
		Customer customer = Customer.find("byUsername", username).first();
		Fund fund =  Fund.find("bySymbol", fundSymbol).first();
		Position position = Position.find("fund=? and customer=?", fund,customer).first();
		if(position==null){
			position= new Position(fund);
			position.save();
		}
		BigDecimal shares = approxQuantity_Data;
		Transaction newTransaction = new Transaction(customer, position, shares, "buy", amount);
		newTransaction.save();
		portfolio();
	}	
	
	//Jin
	public static void sell(String username, String fundSymbol, BigDecimal sellShare,BigDecimal approxQuantity_Data){
		BigDecimal amount= approxQuantity_Data;
		Customer customer = Customer.find("byUsername", username).first();
		Fund fund =  Fund.find("bySymbol", fundSymbol).first();
		Position position = Position.find("fund=? and customer=?", fund,customer).first();
		BigDecimal shares =sellShare;
		Transaction newTransaction = new Transaction(customer, position, shares, "sell", amount);
		newTransaction.save();
		portfolio();
	}	

	//Denise
	public static void history() {
		String username = Security.connected();
		Customer customer = Customer.find("byUsername", username).first();
		List<Transaction> pending = Transaction.find("customer=? and execute_date is null", customer).fetch();
		List<Transaction> executed = Transaction.find("customer=? and execute_date is not null order by execute_date desc", customer).fetch();
		List<BigDecimal> prices = new ArrayList<BigDecimal>();
		for(int i=0; i<pending.size(); i++){
			if(pending.get(i).transaction_type.equalsIgnoreCase("buy") || pending.get(i).transaction_type.equalsIgnoreCase("sell")){
				String symbol = pending.get(i).position.fund.symbol;
				FundPriceHistory latest = FundPriceHistory.find("fund.symbol = ? order by price_date desc", symbol).first();
				if(latest !=null){
					prices.add(latest.price);
				}else{
					prices.add(null);
				}
			}else{
				prices.add(null);
			}
		}
		BigDecimal availableBalance = calculateAvailableBalance(customer);
		render(username, customer, pending, executed, prices, availableBalance);
	}
	
	//Denise
	public static void research(){
		String username = Security.connected();
		
		//Load all fund symbols
		List<Fund> funds = Fund.find("order by symbol asc").fetch();
		for(int i=0; i<funds.size(); i++){
			List<FundPriceHistory> testList = FundPriceHistory.find("fund.symbol=?", funds.get(i).symbol).fetch(10);
			if(testList.size() == 0){
				funds.remove(i);
				i--;
			}
		}
		
		String symbols = "";
		
		for(int i=0; i<funds.size(); i++){
			//Concatenate symbol values into array-like format
			symbols += "'" + funds.get(i).symbol + "'";
			if(i != funds.size()-1){
				symbols += ",";
			}
		}
		render(username, symbols);
	}
	
	//Denise
	public static void getResearchData(String symbol){		
		//Load price history for this symbol
		List<FundPriceHistory> priceHistory = FundPriceHistory.find("fund.symbol=? order by price_date asc", symbol).fetch();
		String dataValues = "[";
		Calendar cal = Calendar.getInstance();	
		for(int j=0; j<priceHistory.size(); j++){
			cal.setTime(priceHistory.get(j).price_date);
			dataValues += "[" + cal.getTimeInMillis() + "," + priceHistory.get(j).price + "]";
			if(j != priceHistory.size()-1){
				dataValues += ",";
			}
		}
		dataValues += "]";
		renderJSON(dataValues);
	}

	//EG
	public static void changeMyPassword() {
		String username = Security.connected();
		Customer customer = Customer.find("byUsername", username).first();
		String firstname = customer.firstname;
		String lastname = customer.lastname;
		String address1 = customer.addr_line1;
		String address2 = customer.addr_line2;
		render(username, firstname, lastname, address1, address2);
	}
	
	//EG
	public static void changeMyPasswordHandler(
			@Required(message="Current password is required")String currentPassword,
			@Required(message="New password is required")String newPassword,
			@Required(message="Retyped new password is required")String retypeNewPassword
			){
		String username = Security.connected();
		Customer customer = Customer.find("byUsername", username).first();
		String firstname = customer.firstname;
		String lastname = customer.lastname;
		String address1 = customer.addr_line1;
		String address2 = customer.addr_line2;
		
		if(validation.hasErrors()) {
			render("CustomerArea/changeMyPassword.html", username, firstname, lastname, address1, address2);
			return;
		}		
		
		if (!currentPassword.equals(customer.password)) {
			validation.addError(null, "Incorrect current password.", "currentPassword");
			render("CustomerArea/changeMyPassword.html", username, firstname, lastname, address1, address2);
			return;			
		}
		
		if (!newPassword.equals(retypeNewPassword)) {
			validation.addError(null, "New passwords do not match.", "newPassword");
			render("CustomerArea/changeMyPassword.html", username, firstname, lastname, address1, address2);
			return;			
		}		
		
		customer.password = newPassword;
		customer.save();
		
		params.put("outcome", "Your password has been successfully updated.");
		params.flash();
		changeMyPassword();
	}
	
	//Denise
	public static BigDecimal calculateAvailableBalance(Customer customer){
		BigDecimal availableBalance = customer.cash;
		
		List<Transaction> pendingTransactions = Transaction.find("customer=? and execute_date is null", customer).fetch();
		for(int i=0; i<pendingTransactions.size(); i++){
			Transaction t = pendingTransactions.get(i);
			if(t.transaction_type.equalsIgnoreCase("buy")){
				availableBalance = availableBalance.subtract(t.amount);
			}else if(t.transaction_type.equalsIgnoreCase("check")){
				availableBalance = availableBalance.subtract(t.amount);
			}
		}		
		return availableBalance;
	}
}
